; Kyle Kelly
; 902588720
; CS2110-B2(HW7)

.orig x3000
MAIN
	LEA R0, PROMPT
;======= Prompt var
	PROMPT .stringz "Please enter well-formed form: "
;=======
	PUTS			;PRINT PROMPT FOR FORM
	LD R4, STRING
	LD R3, STRING_END
	LD R6, STACK_START
	LD R5, STACK_START
	LOOP_INPUT
		GETC
		STR R0, R4, 0 			;Grab character and stor into string buffer
		ADD R4, R4, 1			; buffer index ++
		ADD R1, R0, #-10		; Look for new line terminator
		BRZ INPUT_DONE			; If new-line terminator, leave loop
		ADD R1, R3, R4			; Look for end of string buffer
		BRNP LOOP_INPUT			; If not end of buffer, continue loop
		BRNZP MAX_LENGTH		; Jump past setting null terminator
	INPUT_DONE
		ADD R4, R4, 1				;INCREMENT BUFFER INDEX
		AND R1, R1, 0				;CLEAR R0
		STR R0, R4, 0				;STORE NULL AT END OF STRING
	MAX_LENGTH
	LD R4, STRING				;RESET STRING BUFFER TO FRONT OF STRING
	JSR isForm
	LDR R0, R6, 0	;LOAD RETURN FROM ISFORM
	LDR R1, R4, 0	;LOAD LAST CHAR IN STRING
	ADD R2, R1, -10	;CHECK FOR NEWLINE
	BRNP NOTVALID
	ADD R0, R0, -1	;CHECK FOR ISFORM IS TRUE
	BRNP NOTVALID
		LEA R0, VALID
		PUTS
	BRNZP FINISHED
	NOTVALID
		LEA R0, INVALID
		PUTS
FINISHED
HALT
;===========================
;		Start Variables
;===========================
	STACK_START .fill x6000
	STRING .fill x5000
	STRING_END .fill xAFB2
	INVALID .stringz "Invalid"
	VALID .stringz "Valid"
	

	
;==========================================================
;==========================================================
;					Subroutines
;==========================================================
;==========================================================

;PRECONDITIONS:
;Callee is checking for well-formatted code
;POSTCONDITIONS:
;SP POINTING AT FALSE IF NOT A GOOD FORM
;SP IS POINTING AT 1 IF GOOD FORM
isForm
;========= Set up stack ===========
	ADD R6, R6, -4	;SP+4
	STR R7, R6, 2	; STORE RA
	STR R5, R6, 1	;STORE OLD FP
	ADD R5, R6, 0	;CREATE NEW FP
	STR R0, R5, 0	;STORE OLD R0
	STR R1, R5, -1	;STORE OLD R1
	STR R2, R5, -2	;STORE OLD R2
	ADD R6, R6, -2	;SP +2
;========= Set pre-emptive answer to false
	AND R0, R0, 0	;ZERO R0
	STR R0, R5, 3	;SET PRE-EMPTIVE TO FALSE
;========= isNameCheck ============
	LDR R0, R4, 0	;LOAD NEXT CHAR INTO R0
	ADD R6, R6, -1	;SP+1
	STR R0, R6, 0	;STORE NEXT CHAR ONTO STACK
	JSR isName		;CHECK IF CHAR ISNAME
	ADD R6, R6, 2	;SP-2
	LDR R0, R6, -2	;LOAD RET VAL OF ISNAME INTO R0
	BRP TRUE		;IF ISNAME RETURNED TRUE, BRANCH TO SET ANSWER AS TRUE
;========== isN && isForm check =========
	LDR R0, R4, 0	;LOAD NEXT CHAR INTO R0
	ADD R6, R6, -1	;SP + 1
	STR R0, R6, 0	;STORE NEXT CHAR ONTO STACK
	JSR isN
	LDR R1, R6, 0	;Load ans from isN into R1
	ADD R6, R6, 2	;SP-2
	ADD R1, R1, -1	;CHECK FOR ISN
	BRNP NOTISN
	JSR isForm
	ADD R6, R6, 1	;SP-1
	LDR R0, R6, -1	;Load ans from isForm into R0
	ADD R0, R0, -1	;Check for isForm
	BRZ TRUE
	NOTISN
;=========== isBinaryOperator && isForm && isForm check =========
	LDR R0, R4, 0	;LOAD NEXT CHAR INTO R0
	ADD R6, R6, -1	;SP + 1
	STR R0, R6, 0	;STORE NEXT CHAR ONTO STACK
	JSR isBinaryOperator
	LDR R1, R6, 0	;Load ans from isBinaryOperator into R1
	ADD R6, R6, 2	;SP-2
	ADD R1, R1, -1	;CHECK ISBINARYOPERATOR
	BRNP NOTISBIN
	JSR isForm
	LDR R0, R6, 0	;Load ans from isForm into R0
	ADD R6, R6, 1	;SP-1
	ADD R0, R0, -1	;CHECK FOR ISFORM
	BRNP NOTISBIN
	JSR isForm
	LDR R2, R6,	0	;Load ans from isForm into R2
	ADD R6, R6, 1	;SP-1
	ADD R2, R2, -1	;CHECK ISBIN
	BRZ TRUE
	NOTISBIN
	BRNZP DONE
;===== True means something work, done means it didn't =========
	TRUE
	AND R0, R0, 0	;CLEAR R0
	ADD R0, R0, 1	;R0++
	STR R0, R5, 3	;STORE TRUE 
	DONE
;=========== Break down stack ===========
	LDR R0, R5, 0	;RESTORE OLD R0
	LDR R1, R5, -1	;RESTORE OLD R1
	LDR R2, R5, -2
	ADD R6, R5, 0	;MOVE SP TO CURRENT FP
	LDR R7, R5, #2	;RESTORE RET ADDR
	LDR R5, R5, #1	;RESTORE OLD FP
	ADD R6, R6, #3	;MOVE SP TO RET VAL
	RET


;PRECONDITIONS:
;Callee has pushed current char onto stack	
;POSTCONDITIONS:
;Return val 0 if not N
;Return val 1 if N and increment pointer
isN
	ADD R6, R6, -4	;SP+4
	STR R7, R6, 2	; STORE RA
	STR R5, R6, 1	;STORE OLD FP
	ADD R5, R6, 0	;CREATE NEW FP
	STR R0, R5, 0	;STORE OLD R0
	STR R1, R5, -1	;STORE OLD R1
	ADD R6, R6, -1	;SP +1
	
	AND R0, R0, #0	;CLEAR R0
	STR R0, R5, #3	;PRE-EMPTIVELY STORE FALSE AS ANSWER TO ISN()
	LDR R0, R5, #4	;LOAD IN N INTO R0
	LD 	R1, NCHECK	;LOAD -ASCII OF N INTO R1
	ADD R0, R1, R0	;COMPARE POTENTIAL N TO -N
	BRNP ISNTN		;BRANCH IF NOT N, ELSE STORE TRUE(1) AS RETVAL
		ADD R0, R0, #1		;SET R0 TO 1
		STR R0, R5, #3		;STORE 1(TRUE) INTO RETVAL
		ADD R4, R4, #1		;INCR STRING POINTER
	ISNTN
	LDR R0, R5, 0	;RESTORE OLD R0
	LDR R1, R5, -1	;RESTORE OLD R1
	ADD R6, R5, 0	;MOVE SP TO CURRENT FP
	LDR R7, R5, #2	;RESTORE RET ADDR
	LDR R5, R5, #1	;RESTORE OLD FP
	ADD R6, R6, #3	;MOVE SP TO RET VAL
	RET

;PRECONDITIONS:
;Callee has pushed current char onto stack
;POSTCONDITIONS:
;Ret val is 0 if not a binary operator
;Ret val is 1 if a binary operator and pointer is incremented
;SP pointing at RetVal	
isBinaryOperator
	ADD R6, R6, -4	;SP+4
	STR R7, R6, 2	;STORE RET ADDR
	STR R5, R6, 1	;STORE OLD FP
	ADD R5, R6, 0	;SET NEW FP
	STR R0, R5, 0	;STORE OLD R0
	STR R1, R5, -1	;STORE OLD R1
	STR R2, R5, -2	;STORE OLD R2
	ADD R6, R6, -2	;SP+2
	
	AND R0, R0, #0	;CLEAR R0
	STR R0, R5, 3	;SET FALSE AS ANSWER TO isBinaryOpterator
	LDR R0, R5, 4	;LOAD BINARYOP INTO R0
	LD  R1, ACHECK	;LOAD ACHECK INTO R1
	ADD R2, R1, R0	;COMPARE INPUT AND -A
	BRN DONEBINOP	;BRANCH IF CHAR<A
	LD R1, DCHECK	;LOAD DCHECK INTO R1
	ADD R2, R1, R0	;COMPARE INPUT AND -D
	BRP DONEBINOP	;BRANCH IF CHAR>D
		AND R0, R0, #0	;CLEAR R0
		ADD R0, R0, #1	;INCREMENT R0
		STR R0, R5, 3	;SET RET VAL TO TRUE, SINCE A>=CHAR>=D
		ADD R4, R4, #1	;INCREMENT STR POINTER
	DONEBINOP
	
	LDR R0, R5, 0	;RESTORE OLD R0
	LDR R1, R5, -1	;RESTORE OLD R1
	LDR R2, R5, -2	;RESTORE OLD R2
	ADD R6, R5, 0	;MOVE SP TO CURRENT FP
	LDR R7, R5, 2	;RESTORE RET ADDR
	LDR R5, R5, 1	;RESTORE OLD FP
	ADD R6, R6, 3	;MOVE SP TO RET VAL
	RET

;PRECONDITIONS:
;Callee has pushed current char onto stack
;POSTCONDITIONS:
;Increment pointer for STRING
;Ret val is 0 if not a binary operator
;Ret val is 1 if a binary operator and string pointer is incremented
;SP pointing at RetVal	
isName
	ADD R6, R6, -4	;SP+4
	STR R7, R6, 2	;STORE RET ADDR
	STR R5, R6, 1	;STORE OLD FP
	ADD R5, R6, 0	;SET NEW FP
	STR R0, R5, 0	;STORE OLD R0
	STR R1, R5, -1	;STORE OLD R1
	STR R2, R5, -2	;STORE OLD R2
	ADD R6, R6, -2	;SP+2
	
	AND R0, R0, #0	;CLEAR R0
	STR R0, R5, 3	;SET FALSE AS ANSWER TO isName
	LDR R0, R5, 4	;LOAD BINARYOP INTO R0
	LD  R1, aCHECK	;LOAD aCHECK INTO R1
	ADD R2, R1, R0	;COMPARE INPUT AND -a
	BRN DONEISNAME	;BRANCH IF CHAR<a
	LD R1, zCHECK	;LOAD zCHECK INTO R1
	ADD R2, R1, R0	;COMPARE INPUT AND -z
	BRP DONEISNAME	;BRANCH IF CHAR>z
		AND R0, R0, #0	;CLEAR R0
		ADD R0, R0, #1	;INCREMENT R0
		STR R0, R5, 3	;SET RET VAL TO TRUE, SINCE a>=CHAR>=d
		ADD R4, R4, #1	;INCREMENT STR POINTER
	DONEISNAME
	
	LDR R0, R5, 0	;RESTORE OLD R0
	LDR R1, R5, -1	;RESTORE OLD R1
	LDR R2, R5, -2	;RESTORE OLD R2
	ADD R6, R5, 0	;MOVE SP TO CURRENT FP
	LDR R7, R5, 2	;RESTORE RET ADDR
	LDR R5, R5, 1	;RESTORE OLD FP
	ADD R6, R6, 3	;MOVE SP TO RET VAL
	RET
		

;================================
;		Variables
;================================
	NCHECK .fill #-78
	ACHECK .fill #-65
	aCHECK .fill #-97
	zCHECK .fill #-122
	DCHECK .fill #-68

.orig x5000
INPUT
	.blkw 78
	.fill 10
	.fill 0

.orig x6000
STACK_INIT .fill x0000
	
.end





; We suggest that each of your subroutines have a header following
; the format below:

;PRECONDITIONS:
;	
;	
;	
;POSTCONDITIONS:
;	
;	
;	
;<Subroutine Label Goes Here (without semicolon!)
	; your code here
